package cn.fengsweb.tokyotyrant
{
	import cn.fengsweb.tokyotyrant.define.TokyoTyrantQueryFunctionName;
	import cn.fengsweb.tokyotyrant.define.TokyoTyrantQueryResultType;
	
	import flash.utils.ByteArray;
	
	internal class QueryHandler extends AbstractHandler
	{
		private var _query:TokyoTyrantQuery;
		private var _queryKeyArray:Array;
		private var _sendBytesArray:Array;
		private var _queryValueArray:Array;
		private var _currentKey:String;
		
		public function QueryHandler(host:String, port:uint)
		{
			super(host, port);
		}
		
		public function connect(query:TokyoTyrantQuery, ttr:TokyoTyrantResponder) : void
		{
			_ttc		= new TokyoTyrantConnection(_host, _port, false);
			_ttr		= ttr;
			_query		= query;
			
			switch(_query.resultType){
				case TokyoTyrantQueryResultType.COUNT:
					queryCount();
					break;
				case TokyoTyrantQueryResultType.KEY_ARRAY:
					queryKeyArray();
					break;
			}
		}
		
		private function queryCount():void
		{
			defaultHandler(_query.sendBytes, queryCountSuccessHandler);
		}
		
		private function queryCountSuccessHandler(recvBytes:ByteArray):void
		{
			var rnum:uint	= recvBytes.readUnsignedInt();
			var esiz:uint	= recvBytes.readUnsignedInt();
			var ebuf:String	= recvBytes.readUTFBytes(esiz);
			
			_ttr.result(ebuf);
		}
		
		private function queryKeyArray():void
		{
			defaultHandler(_query.sendBytes, queryKeyArraySuccessHandler);
		}
		
		private function queryKeyArraySuccessHandler(recvBytes:ByteArray):void
		{
			_queryKeyArray		= new Array();
			_sendBytesArray		= new Array();
			_queryValueArray	= new Array();
			
			var rnum:uint	= recvBytes.readUnsignedInt();
			for(var i:uint=0; i<rnum; i++){
				var esiz:uint	= recvBytes.readUnsignedInt();
				var ebuf:String	= recvBytes.readUTFBytes(esiz);
				
				var query:TokyoTyrantQuery	= new TokyoTyrantQuery(TokyoTyrantQueryFunctionName.GET);
					query.addArguments(Util.string2Bytes(ebuf));
					
				_queryKeyArray.push(ebuf);		
				_sendBytesArray.push(query.sendBytes);
			}
			
			iterateGetOne();
		}
		
		private function iterateGetOne():void
		{
			var key:String			= _queryKeyArray.shift();
			var sendBytes:ByteArray	= _sendBytesArray.shift();
			
			if(null != sendBytes){
				_currentKey	= key;
				defaultHandler(sendBytes, getOneSuccessHandler, getOneFailedHandler);
			}else{
				_ttr.result(_queryValueArray);
				_ttc.close();
			}
		}
		
		private function getOneSuccessHandler(recvBytes:ByteArray):void
		{
			var bytes:ByteArray	= new ByteArray();
			recvBytes.readBytes(bytes);
			
			var keyValueObj:Object	= new Object;
				keyValueObj.key		= _currentKey;
				keyValueObj.value	= Util.bytes2Object(bytes);
			_queryValueArray.push(keyValueObj);
			
			iterateGetOne();
		}
		
		private function getOneFailedHandler():void
		{
			var keyValueObj:Object	= new Object;
				keyValueObj.key		= _currentKey;
				keyValueObj.value	= null;
			_queryValueArray.push(keyValueObj);
			
			iterateGetOne();
		}
	}
}